package cn.dengta.context.model;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;

import cn.dengta.common.context.I18N;
import cn.dengta.common.model.ValueProxy;
import cn.dengta.common.model.ValueProxyImpl;
import cn.dengta.common.util.Common;
import cn.dengta.context.web.RequestContextImpl;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.Getter;
import me.codeplayer.util.*;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Getter
public enum Language implements ValueProxyImpl<Language, Integer>, Serializable {
	/** 中文 */
	zh_CN(0, "中文（简体）", "中文", "language.type.zhcn", Country.CN, true),
	/** 繁體 */
	zh(1, "中文（繁體）", "繁体", "language.type.zh", Country.HK, true),
	/** 越南语 */
	vi(3, "Tiếng Việt", "越南语", Country.VN, true),
	/** 韩语 */
	ko_KR(4, "한국어", "韩语", Country.KR, true),
	/** 日语 */
	ja_JP(5, "にほんご", "日语", Country.JP, true),
	/** 泰语 */
	th_TH(6, "ภาษาไทย", "泰语", Country.TH, true),
	/** 印尼语 */
	in_ID(7, "Bahasa Indonesia", "印尼语", Country.ID, true),
	/** 马来西亚语 */
	ms(8, "Melayu", "马来语", Country.MY, true),
	/** 英语 */
	en(2, "English", "英语", "language.type.en", Country.US, true),
	/** 普通牙语 */
	pt(9, "Portugués", "普通牙语", Country.PT, true),
	/** 西班牙语 */
	es(10, "Español", "西班牙语", Country.ES, true),
	//
	;

	private static final long serialVersionUID = 1L;
	/** 默认语言 */
	public static Language DEFAULT = en;

	// 定义私有变量
	@EnumValue
	public final Integer value;
	public final String desc;
	/** 多语言key */
	public final String labelKey;
	@Nonnull
	public final Country country;
	public final boolean show;
	public final Locale locale;
	public final String alias;
	final ValueProxy<Language, Integer> proxy;

	Language(Integer value, String label, String desc, Country country, boolean show) {
		this(value, label, desc, null, country, show);
	}

	Language(Integer value, String label, String desc, String labelKey, Country country, boolean show) {
		this.value = value;
		this.desc = desc;
		this.labelKey = labelKey;
		this.show = show;
		this.country = country;
		this.alias = name().replace('_', '-');
		this.locale = Locale.forLanguageTag(alias);
		this.proxy = new ValueProxy<>(this, value, label);
	}

	public static final Language[] CACHE = ArrayUtil.filter(Language.values(), Language::isShow);
	public static final Language[] ZH_ALL = { zh_CN, zh };

	static final Map<String, Language> mapping = CollectionUtil.toMap(LinkedHashMap::new, Arrays.asList(CACHE), Language::getAlias);

	public static List<Option<String>> NAME_OPTION;
	public static List<Option<String>> FRONT_NAME_OPTION;

	public static List<Option<String>> getNameOption(boolean convert) {
		List<Option<String>> option = convert ? FRONT_NAME_OPTION : NAME_OPTION;
		if (option == null) {
			option = Arrays.stream(CACHE).map(t -> new Option<>(convert ? t.getAlias() : t.name(), t.getLabel())).collect(Collectors.toList());
			if (convert) {
				FRONT_NAME_OPTION = option;
				return option;
			}
			NAME_OPTION = option;
		}
		return option;
	}

	public static String abbrName(Integer value) {
		Language of = of(value);
		if (of != null) {
			return (of == zh_CN ? StringUtils.substringAfter(of.getAlias(), Common.LINE_SEP) : StringUtils.substringBefore(of.getAlias(), Common.LINE_SEP)).toUpperCase();
		}
		return null;
	}

	public boolean forChina() {
		return this == zh_CN || this == zh;
	}

	public static Language of(Integer value) {
		return X.expectNotNull(zh_CN.getValueOf(value), DEFAULT);
	}

	public static Language nameOf(String value) {
		return EnumUtils.getEnum(Language.class, value, null);
	}

	public String msg(String code) {
		return I18N.msg(code, locale);
	}

	public String msg(String code, Object... args) {
		return I18N.msg(code, locale, args);
	}

	@Nonnull
	public static Language of(String language) {
		// 浏览器标准格式："zh-CN,zh;q=0.9"
		if (StringUtil.notEmpty(language)) {
			String[] locales = StringUtils.split(language, ",;", 2);
			Language lang;
			for (String locale : locales) {
				if (locale.length() > 2) {
					lang = mapping.get(locale);
					if (lang != null) {
						return lang;
					}
					locale = locale.substring(0, 2);
				}
				lang = mapping.get(locale);
				if (lang != null) {
					return lang;
				}
			}
		}
		return en;
	}

	/** 获取当前请求中的语言，如果没有从session中获取 */
	public static Language getCurrentReqLanguage() {
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		return attributes != null ? RequestContextImpl.doGetLanguage(attributes.getRequest()) : RequestContextImpl.get().sessionLanguage();
	}
}
